package encrypt_key

import (
	"common/encryp/path"
	"common/kms"
	"common/macaroon"
	"encoding/base64"
	"errors"
	"fmt"
)

type EncryptKeys struct {
	PlainKey   string //原始路径
	EncryptKey []byte //原始路径加密
	DerivedKey []byte //派生Key

	PlainContentKey   []byte //内容加密用的密码
	EncryptContentKey []byte //对plainContentKey 再加密，用于保存数据库
}

type EncryptKey interface {
	CreateEncryptKeys(originKey string) (EncryptKeys, error)                //创建加密key
	DecodeEncryptKeys(plainKey string, encryptedKey []byte) ([]byte, error) //解出加密key
}

type DefaultEncrypt struct {
	apiKey *macaroon.APIKey
}

func NewDefaultEncrypt(key *macaroon.APIKey) *DefaultEncrypt {
	return &DefaultEncrypt{
		apiKey: key,
	}
}

func (d *DefaultEncrypt) CreateEncryptKeys(originKey string) (eks EncryptKeys, err error) {
	//加密路径
	//unEncryKey 处理过去掉前后空格，/号的key
	//encObjectKey ： unEncryKey 的加密处理key
	eks.EncryptKey, eks.PlainKey, err = path.EncPath(originKey, d.apiKey.RootKey()) //todo 不应用rootkey，用derived key
	if err != nil {
		return
	}
	//up.Log.Debug(fmt.Sprintf("路径加密: %s => %x \n", unEncryKey, encObjectKey))

	//计算加密内容的密钥contentKey，它与路径，rootkey相关
	//encryptedKey: 对contentKey 的加密

	derivedKey := path.GetDerivedKey(d.apiKey.RootKey(), eks.PlainKey)
	eks.PlainContentKey, eks.EncryptContentKey, err = path.GetContentKey(derivedKey)
	return
}

func (d *DefaultEncrypt) DecodeEncryptKeys(plainKey string, encryptedKey []byte) (res []byte, err error) {
	//计算contentKey
	derivedKey := path.GetDerivedKey(d.apiKey.RootKey(), plainKey)
	contentKey, err := path.ParseContentKey(encryptedKey, derivedKey)
	//fmt.Printf("内容密钥加密  %x contentKey %x\n", respRespone.EncryptedKey, contentKey)
	if err != nil {
		return nil, fmt.Errorf("ParseContentKey failed: %s", err)
	}
	return contentKey, nil
}

type KmsEncrypt struct {
	kms    *kms.Client
	apiKey *macaroon.APIKey
}

func NewKmsEncrypt(kms *kms.Client, key *macaroon.APIKey) *KmsEncrypt {
	return &KmsEncrypt{
		kms:    kms,
		apiKey: key,
	}
}

func (d *KmsEncrypt) CreateEncryptKeys(originKey string) (eks EncryptKeys, err error) {
	eks.EncryptKey, eks.PlainKey, err = path.EncPath(originKey, d.apiKey.RootKey()) //todo 不应用rootkey，用derived key
	if err != nil {
		return
	}

	kmsRes, err := d.kms.GenerateDataKey(&kms.GenerateDataKeyReq{Keyid: d.apiKey.KeyId(), Keylen: 16})
	if err != nil {
		return
	}
	plainKey, base64Err := base64.StdEncoding.DecodeString(kmsRes.Result.Plaintext)
	if base64Err != nil {
		return
	}
	if len(plainKey) != 16 {
		err = errors.New(("plainKey != 16"))
		return
	}
	eks.PlainContentKey = plainKey
	eks.EncryptContentKey = []byte(kmsRes.Result.Ciphertext)
	return
}

func (d *KmsEncrypt) DecodeEncryptKeys(_ string, encryptedKey []byte) (res []byte, err error) {
	kmsRes, err := d.kms.Decrypt(&kms.DecryptReq{Keyid: d.apiKey.KeyId(), Ciphertext: string(encryptedKey)})
	if err != nil {
		return nil, fmt.Errorf("ParseContentKey failed: %s", err)
	}
	plainKey, base64Err := base64.StdEncoding.DecodeString(kmsRes.Result.Plaintext)
	if base64Err != nil {
		return nil, err
	}
	return plainKey, nil
}
